import { Dimensions, useWindowDimensions } from "react-native";
import { useEffect, useState } from "react";

const screenSize = {
  sm: "640px",
  md: "768px",
  lg: "1024px",
  xl: "1280px",
  "2xl": "1536px",
};

type breakpoints = keyof typeof screenSize | "default";

type MediaQueriesBreakpoints = {
  key: breakpoints;
  breakpoint: number;
  isValid: boolean;
  value?: unknown;
};

type BreakPointValue = Partial<Record<breakpoints, unknown>>;

const resolveScreenWidth: Record<breakpoints, number> = {
  default: 0,
};

Object.entries(screenSize).forEach(([key, value]) => {
  if (typeof value === "string") {
    resolveScreenWidth[key] = parseInt(value.replace("px", ""), 10);
  }
});

export const getBreakPointValue = (
  values: BreakPointValue,
  width: number
): unknown => {
  if (typeof values !== "object") return values;

  let finalBreakPointResolvedValue: unknown;
  const mediaQueriesBreakpoints: Array<MediaQueriesBreakpoints> = [
    {
      key: "default",
      breakpoint: 0,
      isValid: true,
    },
  ];
  Object.keys(resolveScreenWidth).forEach((key) => {
    const isValid = isValidBreakpoint(resolveScreenWidth[key], width);

    mediaQueriesBreakpoints.push({
      key: key,
      breakpoint: resolveScreenWidth[key],
      isValid: isValid,
    });
  });

  mediaQueriesBreakpoints.sort(
    (a: MediaQueriesBreakpoints, b: MediaQueriesBreakpoints) =>
      a.breakpoint - b.breakpoint
  );

  mediaQueriesBreakpoints.forEach(
    (breakpoint: MediaQueriesBreakpoints, index: number) => {
      breakpoint.value = values.hasOwnProperty(breakpoint.key)
        ? values[breakpoint.key]
        : mediaQueriesBreakpoints[index - 1]?.value ||
          mediaQueriesBreakpoints[0]?.value;
    }
  );

  const lastValidObject = getLastValidObject(mediaQueriesBreakpoints);

  if (!lastValidObject) {
    finalBreakPointResolvedValue = values;
  } else {
    finalBreakPointResolvedValue = lastValidObject.value;
  }
  return finalBreakPointResolvedValue;
};

export function useBreakpointValue(values: BreakPointValue): unknown {
  const { width } = useWindowDimensions();

  const [currentBreakPointValue, setCurrentBreakPointValue] = useState<unknown>(
    getBreakPointValue(values, width)
  );

  useEffect(() => {
    if (typeof values === "object") {
      const finalBreakPointResolvedValue = getBreakPointValue(values, width);
      setCurrentBreakPointValue(finalBreakPointResolvedValue);
    }
  }, [values, width]);

  if (typeof values !== "object") return values;

  return currentBreakPointValue;
}

export function isValidBreakpoint(
  breakPointWidth: number,
  width: number = Dimensions.get("window")?.width || 0
) {
  const windowWidth = width;

  return windowWidth >= breakPointWidth;
}

function getLastValidObject(
  mediaQueries: Array<{
    key: breakpoints;
    breakpoint: number;
    isValid: boolean;
    value?: unknown;
  }>
) {
  for (let i = mediaQueries.length - 1; i >= 0; i--) {
    if (mediaQueries[i].isValid) {
      return mediaQueries[i];
    }
  }
  return null; // No valid object found
}
